import { _decorator, clamp, Component, Layout, Node, Prefab, SpriteComponent, SpriteFrame, tween, UITransform, Vec3 } from 'cc';
import { constant } from '../framework/constant';
import { poolManager } from '../framework/poolManager';
const { ccclass, property } = _decorator;

@ccclass('playerBloodBar')
export class playerBloodBar extends Component {


    @property
    /** 中间线的宽度 */
    public lineWidth: number = 1;//

    @property(Prefab)
    /** 中间线预制体 */
    public pbLine: Prefab = null!//

    @property(Node)
    /** 血块容器 */
    public ndContainer: Node = null!;//


    @property(Layout)
    /** container节点的layout组件 */
    public layoutContainer: Layout = null!;//

    @property(UITransform)
    /** 白色进度条的UI组件 */
    public UIComWhiteBar: UITransform = null!;//

    @property(Node)
    /** 白色进度条节点 */
    public ndWhiteBar: Node = null!;//

    @property(UITransform)
    /** 血量进度条的UI组件 */
    public UIComCurBloodBar: UITransform = null!;//

    @property(Node)
    /** 血量进度条节点 */
    public ndCurBloodBar: Node = null!;//

    @property(SpriteComponent)
    /** 血条背景色 */
    public spComBloodBar: SpriteComponent = null!;

    @property(SpriteFrame)
    /** 小怪和bos是红色背景 */
    public sfRed: SpriteFrame = null!//

    @property(SpriteFrame)
    /**玩家是绿色背景 */
    public sfGreen: SpriteFrame = null!//

    @property(UITransform)
    /** 血条容器节点 */
    public UIComBloodBar: UITransform = null!;//

    /** 最小整体血条宽度 */
    private _minBloodBarWidth: number = 100;//
    /** 当前整体血条宽度 */
    private _bloodBarWidth: number = 0;//
    /** 最小单个血块宽度 */
    private _minBloodBarItemWidth: number = 10;//
    /** 每隔血条 */
    private _maxItemBlood: number = 200;//
    /** 总的血量 */
    private _totalBlood: number = 0;//
    /** 跟随目标 */
    private _ndTarget: Node = null!;//
    /** 偏差 */
    private _offsetPos: Vec3 = null!;//
    private _curPos: Vec3 = new Vec3()!;//当前血条位置
    private _curBlood: number = 0;//当前血量值
    private _scriptParent: any = null!;//血条所在节点绑定的脚本
    private _scale: Vec3 = new Vec3();//血条缩放倍数
    private _bloodBarHeight: number = 15;//血条高度
    private _oriContainerPos: Vec3 = new Vec3();//初始线条容器节点位置
    private _curContainerPos: Vec3 = new Vec3();//当前线条容器节点位置
    private _bloodBarPos = new Vec3();//血条位置
    private _whiteBarPos = new Vec3();//白条位置


    /**
     * 刷新血量
     *
     * @param {number} num 血量值
     * @param {boolean} [isIncreaseLimit=false] //是否增加上限
     * @memberof PlayerBloodBar
     */
    public refreshBlood(num: number, isIncreaseLimit: boolean = false) {
        this._curBlood += num;
        this._curBlood = clamp(this._curBlood, 0, this._totalBlood);
        let ratio = this._curBlood / this._totalBlood;

        if (num < 0) {//减血
            ratio = ratio <= 0 ? 0 : ratio;

            this.UIComCurBloodBar.setContentSize(this._bloodBarWidth * ratio, this._bloodBarHeight * 0.8);

            if (ratio > 0) {
                this.ndContainer.children.forEach((ndChild: Node) => {
                    let spComLine = ndChild.getComponent(SpriteComponent) as SpriteComponent;

                    if (spComLine.enabled && ndChild.position.x > this._bloodBarWidth * ratio) {
                        spComLine.enabled = false;
                    }
                })

                tween(this.UIComWhiteBar)
                    .to(0.7, { width: this._bloodBarWidth * ratio })
                    .call(() => {

                    })
                    .start();
            } else {
                // poolManager.instance.putNode(this.node);
                this.node.active = false;
                this._scriptParent.isDie = true;
                this._curBlood = 0;
            }
        } else {//加血
            if (isIncreaseLimit) {//增加上限,并增加多出来的血量，最多不超过上限
                this._curBlood += num;
                this._totalBlood += num;
                this._curBlood = this._curBlood >= this._totalBlood ? this._totalBlood : this._curBlood;
                ratio = this._curBlood / this._totalBlood;
            } else {//普通加血，最多不超过上限                
                ratio = ratio >= 1 ? 1 : ratio;
            }

            tween(this.UIComCurBloodBar)
                .to(1, { width: this._bloodBarWidth * ratio })
                .call(() => {
                    this.show(this._scriptParent, this._totalBlood, this._offsetPos, this._scale, null, false);

                })
                .start();
        }
    }

    /**
     * 展示血条
     *
     * @param {*} scriptParent 血条使用者绑定的节点，如玩家或者小怪
     * @param {number} totalBlood 总血量
     * @param {number} bloodBarType 血条类型
     * @param {Vec3} offsetPos 血条位置偏差
     * @param {Vec3} scale 血条缩放大小
     * @param {(Function | null)} [callback] 
     * @param {boolean} [isInit=true] 是否是初次展示，初次展示则显示完整血量，否则刷新的时候展示当前血量
     * @memberof BloodBar
     */
    public show(scriptParent: any, totalBlood: number, offsetPos: Vec3, scale: Vec3, callback?: Function | null, isInit: boolean = true) {
        this._scriptParent = scriptParent!;
        this._totalBlood = totalBlood;
        this._offsetPos = offsetPos;
        this._scale = scale;
        this._ndTarget = scriptParent.node;

        this.node.setScale(scale);

        if (isInit) {
            this._curBlood = this._totalBlood;
        }

        //血块数量
        let bloodItemNum = Math.ceil(totalBlood / this._maxItemBlood);
        //当前血量条最小长度
        this._bloodBarWidth = this._minBloodBarItemWidth * bloodItemNum;
        //所需血条总宽度大于最小整体血条宽度，需增大血条大小，反之使用最小血条宽度
        let isOutOfRange = this._bloodBarWidth > this._minBloodBarWidth;

        this._oriContainerPos.set(this.ndContainer.position);

        if (isOutOfRange) {
            this._curContainerPos.set(-this._bloodBarWidth * 0.5, this._oriContainerPos.y, 0);
            this.ndContainer.setPosition(this._curContainerPos);
        } else {
            this._bloodBarWidth = this._minBloodBarWidth;
        }

        //每个间隔线之间的距离，1为它本身的宽度，默认前后不显示
        this.layoutContainer.spacingX = this._bloodBarWidth / bloodItemNum - 1;

        this.ndContainer.children.forEach((item: any) => {
            item.active = false;
        })

        //当前血量占全部的比例
        let ratio = this._curBlood / this._totalBlood;
        ratio = clamp(ratio, 0, 1);

        //设置整体大小
        this.UIComBloodBar.setContentSize(this._bloodBarWidth + 2, this._bloodBarHeight);
        this.UIComBloodBar.priority = constant.PRIORITY.BLOOD;

        //根据当前血量刷新中间连接线
        for (let i = 0; i < bloodItemNum + 1; i++) {
            let ndLineItem: Node;

            if (i >= this.ndContainer.children.length) {
                ndLineItem = poolManager.instance.getNode(this.pbLine, this.ndContainer);
            } else {
                ndLineItem = this.ndContainer.children[i];
            }

            ndLineItem.active = true;

            let UICom = ndLineItem.getComponent(UITransform) as UITransform;

            if (i % 5 === 0) {
                UICom.setContentSize(1.5, 7);
            } else {
                UICom.setContentSize(1, 5);
            }
        }

        let layCom = this.ndContainer.getComponent(Layout) as Layout;
        //立即执行更新布局
        layCom.updateLayout();

        //头尾不展示中间线
        this.ndContainer.children.forEach((ndLineItem: Node, i: number) => {
            let spComLine = ndLineItem.getComponent(SpriteComponent) as SpriteComponent;
            if (i === 0 || i === bloodItemNum || ndLineItem.position.x > this._bloodBarWidth * ratio) {
                spComLine.enabled = false;
            } else {
                spComLine.enabled = true;
            }
        })

        //设置白色进度条长度和位置
        this.UIComWhiteBar.setContentSize(ratio * this._bloodBarWidth, this._bloodBarHeight * 0.8);
        this._whiteBarPos.set(this.ndContainer.position.x, 0.5, this.ndContainer.position.z);
        this.ndWhiteBar.setPosition(this._whiteBarPos);

        //设置血量进度条长度和位置
        this.UIComCurBloodBar.setContentSize(ratio * this._bloodBarWidth, this._bloodBarHeight * 0.8);
        this._bloodBarPos.set(this.ndContainer.position.x, 0, this.ndContainer.position.z);
        this.ndCurBloodBar.setPosition(this._bloodBarPos);

        callback && callback();
    }
}


